<!--
 * @Description: 聊天界面
 * @Author: Kerwin
 * @Date: 2023-07-25 10:21:35
 * @LastEditTime: 2025-04-14 14:41:06
 * @LastEditors:  Please set LastEditors
-->
<template>
  <view class="container" v-if="parentLoaded">
    <u-navbar :title="conversationInfo.name" :custom-back="gotabpolice" >
      <view slot="right" v-if="!configStore.hideData && conversationType === ConversationType.GROUP">
        <u-icon class="u-m-r-30" name="more-dot-fill" size="40" @click="toGroupDetail"></u-icon>
      </view>
    </u-navbar>
    <view class="l-chat-body" @tap="onChatClick">
      <!-- :scroll-top="chatScrollTop" -->
      <!-- :scroll-into-view="bottomId" -->

      <scroll-view scroll-y="true" class="l-char-scroll" scroll-with-animation :scroll-top="chatScrollTop"
        :class="{ 'l-char-scroll-height': isScrollHeight }">
        <view class="l-char-scroll-content">
          <view class="l-char-empty"> 已经没有聊天记录了~ </view>
          <template v-for="(s, i) in chatList" :key="i">
            <view class="l-chat-item" :class="{
              'l-chat-mine': s.messageDirection === 1
            }" :id="'msg' + i" @longpress="onLongPress($event, s, i)">
              <view class="l-chat-item-time" v-if="showTime(i)">
                {{ dateFormat(new Date(s.sentTime), 'MM-dd hh:mm') }}
              </view>
              <view class="l-chat-item-time" v-if="s.messageType === 'RC:RcCmd'"> {{ parseInt(s.senderUserId) ==
                userinfo.id ? '我' : getNickname(s) }}撤回了一条消息 </view>
              <view class="l-chat-item-content" v-else>
                <view class="l-chat-avatar">
                  <u-image width="80" height="80" border-radius="8" :loading-icon="avatar_def" :error-icon="avatar_def"
                    :src="getAvatar(s)" :lazy-load="false" :fade="false" bg-color="transparent"
                    mode="aspectFill"></u-image>
                </view>
                <view class="l-chat-view">
                  <view class="l-chat-name">{{ getNickname(s) }}</view>
                  <template v-if="s.messageType == 'RC:TxtMsg'">
                    <view class="l-chat-text">
                      {{ s.content.content || '' }}
                    </view>
                  </template>
                  <template v-else-if="s.messageType === 'RC:ImgMsg'">
                    <view>
                      <u-image @tap="
                        previewImage([getImgFullPath(s.content.imageUri)])
                        " :src="getImgFullPath(s.content.imageUri)" :style="{ 'max-width': '250rpx' }" width="250rpx"
                        height="auto" mode="scaleToFill" border-radius="14" class="l-upload-img"></u-image>
                    </view>
                  </template>
                  <template v-else-if="s.messageType === 'RC:LBSMsg'">
                    <view class="l-chat-location" @click="
                      handleMapLocation({
                        latitude: s.content.latitude,
                        longitude: s.content.longitude,
                        addr: s.content.content
                      })
                      ">
                      <view class="l-chat-con">
                        <view class="name">{{ s.content.content }}</view>
                      </view>
                      <map :longitude="s.content.longitude" :latitude="s.content.latitude"
                        style="width: 350rpx; height: 180rpx"></map>
                    </view>
                  </template>
                  <template v-else-if="s.messageType === 'RC:ReferenceMsg'">
                    <view class="l-chat-text">
                      {{ s.content.content || '' }}
                    </view>
                    <view class="l-chat-text-refer">
                      <view class="rname">{{ s.content.referMsgUserId }}:</view>
                      <view class="rcon" v-if="s.content.objName == 'RC:TxtMsg'">
                        {{ s.content.referMsg.content }}
                      </view>
                      <view class="rimg" v-if="s.content.objName == 'RC:ImgMsg'">
                        <u-image :src="s.content.referMsg.imageUri" :width="'100%'" :height="'auto'" mode="scaleToFill"
                          border-radius="10" @tap="previewImage([s.content.referMsg.imageUri])"></u-image>
                      </view>
                    </view>
                  </template>
                  <template v-else-if="s.messageType === 'KX:HongBao'">
                    <view class="message-red-packet" :class="{ chai: !s.content.status }" @click="openhb(s, i)">
                      <view class="contents">
                        <u-image mode="scaleToFill" :loading-icon="hongbao" :error-icon="hongbao" :lazy-load="false"
                          :fade="false" :width="s.content.status === 1 ? 70 : 60"
                          :src="s.content.status == 1 ? hongbao : hongbao_chai"></u-image>
                        <view class="packet">
                          <view class="name">{{
                            s.content?.toUserId
                              ? `恭喜：${s.content?.nickname}`
                              : `${s.content?.title}`
                          }}</view>
                          <view class="content">{{
                            s.content?.toUserId
                              ? '获得一个红包'
                              : s.content.content
                          }}</view>
                        </view>
                      </view>
                      <view class="footer u-border-top">
                        <text>{{
                          (s.content?.toUserId
                            ? s.content?.title.split('-')[0]
                            : s.content?.redPacketTypeName) || '开心红包'
                        }}</text>
                        <text v-if="s.content.status === 0">已领取</text>
                      </view>
                    </view>
                  </template>
                  <template v-else-if="s.messageType === 'KX:Product'">
                    <view class="msg-product" @click="toProductDetail(s.content)">
                      <view class="imgCover">
                        <view class="content">
                          <view class="name">{{ s.content.title }}</view>
                        </view>
                        <u-image class="img" border-radius="0" :src="getImgFullPath(s.content.imageUrl)" width="300rpx"
                          :lazy-load="true" mode="scaleToFill" />
                      </view>
                    </view>
                  </template>
                  <template v-else-if="s.messageType === 'KX:PinTuan'">
                    <view class="msg-product" @click="toPinTuanDetail(s.content)">
                      <view class="content">
                        <view class="name">{{ s.content.title }}</view>
                      </view>
                      <view class="imgCover">
                        <u-image class="img" border-radius="0" :src="getImgFullPath(s.content.imageUrl)" height="300rpx"
                          :lazy-load="true" mode="scaleToFill" />
                      </view>
                    </view>
                  </template>
                </view>
              </view>
            </view>
          </template>
        </view>
      </scroll-view>
    </view>
    <c_msgpup ref="msgpupRef" :conversation-type="conversationType" :msgPupData="msgPupData" @reference="setReferFn"
      @delete="msgDelete" @recall="msgRecall"></c_msgpup>
    <c_hongbao ref="hongBaoRef" :conversation-type="conversationType" :target-id="targetId"
      :circleId="conversationInfo.cid" @received="msgHongbaoUpdate" />
    <c_foot ref="footerRef" @on-focus="setChatScrollHeight" :conversation-type="conversationType" :target-id="targetId"
      :referMessage="referMessage" @closeRefer="setReferFn" @showPacket="sendRedPacket" />
  </view>
</template>
<script setup lang="ts">
import { reactive, ref, computed, watch, onUnmounted } from 'vue'
import { onLoad, onShow } from '@dcloudio/uni-app'
import { storeToRefs } from 'pinia'
import { baseApi, socialApi, userApi } from '@/api';
import {
  getImgFullPath,
  previewImage,
  dateFormat,
  handleMapLocation
} from '@/utils/index'
import { useConfigStore, useChatStore, useUserStore } from '@/store'
import avatar_def from '../../static/img/avatar_default.svg'
import c_foot from './c_foot.vue'
import c_msgpup from './c_msgpup.vue'
import c_hongbao from './c_hongbao.vue'
import { route } from '@/utils/common'
import hongbao from '../../static/img/hongbao.png'
import hongbao_chai from '../../static/img/red-chai.png'
import { Message } from '@/packageD/common/rongCloud/msgType'
import RongIMLib from '@/packageD/common/rongCloud/im_init'
import { IAReceivedMessage, ConversationType } from '@rongcloud/imlib-next';

const parentLoaded = ref(false)
const configStore = useConfigStore()
const ryStore = useChatStore()
const userStore = useUserStore()
const { messagelist, allGroupUsers, currentConversationHistoryMessageList, userinfo } = storeToRefs(ryStore)
const targetId = ref()
const chatList = computed(() => {
  const msglist = currentConversationHistoryMessageList.value
  return msglist
})
// 获取消息展示头像
const getAvatar = (s: IAReceivedMessage) => {
  try {
    let s_user;
    if (s.conversationType === RongIMLib.ConversationType.GROUP) {
      const groupUsers = allGroupUsers.value?.[s.targetId];
      if (!groupUsers) {
        console.warn(`群组用户数据缺失: targetId=${s.targetId}`);
        return avatar_def;
      }
      s_user = groupUsers.find(item => item.userId.toString() === s.senderUserId)?.user;
    } else if (s.conversationType === RongIMLib.ConversationType.PRIVATE) {
      s_user = p_conversation_users.value?.find(item => item.id.toString() === s.senderUserId);
    }
    return s_user ? getImgFullPath(s_user.avatar) : avatar_def;
  } catch (error) {
    console.error('获取头像失败:', error);
    return avatar_def;
  }
};
// 获取消息展示昵称
const getNickname = (s: IAReceivedMessage) => {
  try {
    let s_user;
    if (s.conversationType === RongIMLib.ConversationType.GROUP) {
      const groupUsers = allGroupUsers.value?.[s.targetId];
      if (!groupUsers) {
        console.warn(`群组用户数据缺失: targetId=${s.targetId}`);
        return '未知昵称';
      }
      s_user = groupUsers.find(item => item.userId.toString() === s.senderUserId)?.user;
    } else if (s.conversationType === RongIMLib.ConversationType.PRIVATE) {
      s_user = p_conversation_users.value?.find(item => item.id.toString() === s.senderUserId);
    }
    return s_user ? s_user.nickname : '未知昵称';
  } catch (error) {
    console.error('获取昵称失败:', error);
    return '未知昵称';
  }
};
function getHistoryMessages() {
  ryStore.getHistoryMessages(targetId.value, conversationType.value)
}
const promise = Promise.resolve()
function nextTick(callback?: Function) {
  return promise.then(callback)
}
const isScrollHeight = ref(false)
const scrollView = ref()
function setChatScrollHeight(arg_isScrollHeight?: boolean | undefined) {
  isScrollHeight.value = arg_isScrollHeight || false
}
function setChatScrollTop() {
  chatScrollTop.value += 10
  bottomId.value = `msg${chatList.value.length - 1}`
}
const bottomId = ref(`msg${chatList.value.length - 1}`)
watch(
  chatList,
  (n) => {
    if (n) {
      setChatScrollHeight()
      nextTick(setChatScrollTop)
    }
  },
  { deep: true }
)
const chatScrollTop = ref(999999)
const conversationInfo = reactive({
  name: '',
  gid: '',
  cid: ''
})
const footerRef = ref()
function onChatClick() {
  footerRef.value?.onChatClick()
}

// 是否显示消息日期
function showTime(i: number) {
  if (i === 0) return true
  const s_time = chatList.value[i - 1]?.sentTime
  const e_time = chatList.value[i]?.sentTime
  return e_time - s_time > 60 * 1000
}
// 长按消息监听
const msgPupData = ref({})
const message_checked = ref<Message | null>(null)
const message_checked_index = ref()
const msgpupRef = ref()
function onLongPress(e: { message?: any }, message: any, i: number) {
  e.message = message
  msgPupData.value = e
  message_checked.value = message
  message_checked_index.value = i
  setTimeout(() => {
    msgpupRef.value?.showPop()
  }, 200)
}
// 引用消息
const referMessage = ref<null | Object>(null)
function setReferFn(data: Object | null) {
  referMessage.value = data
}

function toGroupDetail() {
  route({
    url: '/packageD/pages/chatGroup/detail',
    params: {
      gid: targetId.value,
      cid: conversationInfo.cid
    }
  })
}

// 点击红包
const hongBaoRef = ref()
function openhb(message: Message, i: any) {
  message_checked.value = message
  message_checked_index.value = i
  if (message.content.status == 1) {
    hongBaoRef.value.openhb(message)
  } else {
    route({
      url: '/packageA/pages/hongBaoRecord/index',
      params: {
        id: message.content.friendCircleRedPacketId,
        targetId: targetId.value
      }
    })
  }
}
// 发送红包
function sendRedPacket() {
  hongBaoRef.value.sendRedPacketShow()
}
enum MsgContentStatus {
  UNREAD = 1,
  READ = 0
}
// 更新消息
function msgHongbaoUpdate() {
  if (!message_checked.value) return
  message_checked.value.content.status = 0
  ryStore.setMessage(
    message_checked.value,
    'update',
    message_checked_index.value
  )
  // 更新红包消息扩展数据
  ryStore.updateMessageExpansion(message_checked.value, { isOpen: '1' })
}
// 删除消息
function msgDelete() {
  ryStore.setMessage(
    message_checked.value,
    'delete',
    message_checked_index.value
  )
}
// 撤回消息
async function msgRecall(message: {
  targetId: any
  messageUId: any
  sentTime: any
  content: any
  messageType: any
}) {
  const { targetId, messageUId, sentTime } = message
  const params = {
    targetId,
    messageUId,
    sentTime,
    conversationType: conversationType.value
  }
  const { data } = await ryStore.recallMessage(params)
  ryStore.updateRecalledMsg(data as any)
}
// 获取群成员
async function getChatGroupUsers() {
  if (allGroupUsers.value[targetId.value]) return
  const { data } = await socialApi.getChatGroupUsers({
    friendCircleId: parseInt(conversationInfo.cid),
    noPaging: true
  })
  console.log('获取群成员==>', data);

  ryStore.setGroupUser({ targetId: targetId.value, userList: data }, 'add')
}
// 点击产品消息
function toProductDetail(product: { shopId: any; productId: any }) {
  const { shopId, productId } = product
  uni.navigateTo({
    url: `/packageA/pages/productDetail/index?shopId=${shopId}&productId=${productId}`
  })
}
// 点击拼团消息
function toPinTuanDetail(data: { orderId: any }) {
  const { orderId } = data
  uni.navigateTo({
    url: `/packageB/pages/pinTuan/detail?orderId=${orderId}`
  })
}
const conversationType = ref(RongIMLib.ConversationType.PRIVATE)
const friend_userInfo = ref()
const p_conversation_users = ref([
  { ...userStore.userInfo, userId: ryStore.userinfo.id },
])

//群详情
async function getGroupList() {
  uni.showLoading()
  const { data } = await socialApi.getUserChatGroup({
    userId: userStore?.userInfo?.id,
    noPaging: true
  }).finally(() => {
    uni.hideLoading()
  })
  console.log('获取用户全部群聊==>', data);
  if (data && data.length > 0) {
    conversationInfo.name = data[0]?.name
  }else {
    conversationInfo.name =  ''
  }


}


//融云链接
const initRongCloud = () => {
  const { Events } = RongIMLib
  RongIMLib.addEventListener(Events.CONNECTING, () => {
    console.log('正在链接服务器')
  })
  RongIMLib.addEventListener(Events.CONNECTED, () => {
    console.log('已经链接到服务器')
    const includeMuted = false
    const conversationTypes = [
      RongIMLib.ConversationType.PRIVATE,
      RongIMLib.ConversationType.GROUP
    ]
    RongIMLib.getTotalUnreadCount(includeMuted, conversationTypes)
      .then((res) => {
        if (res.code === 0) {
          console.log('未读消息', res.data)
        } else {
          console.log(res.code, res.msg)
        }
      })
      .catch((error) => {
        console.log(error)
      })
    RongIMLib.addEventListener(Events.MESSAGES, (evt) => {
      const { messages } = evt
      console.log('listener==>', evt)
      if (messages && messages.length > 0) {
        messages.forEach((message) => {
          ryStore.setMessage(message, 'add')
        })
      }
    })
    RongIMLib.addEventListener(Events.EXPANSION, (evt) => {
      console.log('扩展信息：', evt)
      const { updatedExpansion, deletedExpansion } = evt;
      console.log('拓展信息更新：', updatedExpansion);
      console.log('拓展信息删除：', deletedExpansion);
    })
    RongIMLib.addEventListener(Events.CONVERSATION, (evt) => {
      console.log('会话监听：', evt);
      ryStore.updateConversation(evt)
    })
  })
}
// 获取用户融云token并建立链接
const getRongCloudToken = async () => {
  uni.showLoading({
    title: '加载中',
    mask: true
  })
  const { code, data } = await userApi.getRongCloudToken(userStore.userInfo?.id).finally(() => {
    uni.hideLoading()
  })
  if (code === 200) {
    const res = await ryStore.connect(data)
    if (res) {
      ryStore.updateMyUserProfile({
        name: userStore.userInfo?.nickname,
        portraitUri: getImgFullPath(userStore.userInfo?.avatar)?.replace(/^https:\/\/|^http:\/\//, "//")
      })
    }
  }
}



//返回
const gotabpolice = () =>{
  uni.redirectTo ({
      url: '/packageD/pages/index/index?tab=0&isShop=false'
    });
}





onShow(() => {
  initRongCloud()
  getRongCloudToken()
})

onLoad(async (option) => {
  parentLoaded.value = true;
  targetId.value = option?.targetId;
  conversationType.value = parseInt(option?.conversationType);

  await Promise.all([getHistoryMessages(), getGroupList()]);

  if (conversationType.value === RongIMLib.ConversationType.GROUP) {
    conversationInfo.gid = option?.groupId;
    conversationInfo.cid = option?.targetId;
    await getChatGroupUsers();
  } else if (conversationType.value === RongIMLib.ConversationType.PRIVATE) {
    const { code, data } = await userApi.userInfo({ id: option?.userId });
    if (code === 200) {
      conversationInfo.name = data?.nickname;
      friend_userInfo.value = data;
      p_conversation_users.value.push(data);
    }
  }
});
</script>


<style lang="scss" scoped>
@import '@/styles/helper.scss';

.container {
  :deep(.u-slot-content) {
    justify-content: flex-end;
  }
}

.l-chat-body {
  width: 100%;
  flex: 1;
}

.l-char-scroll {
  width: 100%;
  /* #ifdef H5 */
  height: calc(100vh - 190rpx);
  /* #endif */
  /* #ifndef H5 */
  height: calc(100vh - 300rpx);
  /* #endif */
  background-color: #f6f6f6;
}

.l-char-scroll-height {
  /* #ifdef H5 */
  height: calc(100vh - 190rpx - 350rpx);
  /* #endif */
  /* #ifndef H5 */
  height: calc(100vh - 250rpx - 350rpx);
  /* #endif */
}

.l-char-content {
  width: 100%;
  box-sizing: border-box;
  padding: 40rpx 20rpx 40rpx;
}

.l-char-scroll-content {
  padding: 0 20rpx 20rpx;
  width: 100%;
  box-sizing: border-box;
  overflow-y: scroll;
}

.l-chat-item {
  width: 100%;
  font-size: 32rpx;
  margin-bottom: 20rpx;
}

.l-char-empty,
.l-chat-item-time {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  height: 92rpx;
  font-size: 24rpx;
  color: #999999;
}

.l-chat-item-content {
  display: flex;
}

.l-chat-img-avatar,
.l-chat-avatar {
  width: 80rpx;
  height: 80rpx;
  border-radius: 50%;
}

.l-chat-avatar {
  margin: 0 20rpx 0 0;
}

.l-chat-view {
  max-width: 515rpx;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
}

.l-chat-name {
  width: 100%;
  font-size: 24rpx;
  color: #666666;
  margin-bottom: 10rpx;
  @include ellipsis();
}

.l-chat-text {
  min-width: 100rpx;
  max-width: 515rpx;
  padding: 15rpx 30rpx;
  box-sizing: border-box;
  background-color: #ffffff;
  position: relative;
  word-break: break-all;
  border-radius: 3px;
  font-size: 30rpx;
}

.l-chat-text::after {
  content: ' ';
  display: block;
  position: absolute;
  top: 34rpx;
  width: 0;
  height: 0;
  left: -18rpx;
  transform: translate(0, -50%);
  border: 10rpx solid;
  border-color: transparent #ffffff transparent transparent;
}

.l-chat-text-refer {
  background: rgba(0, 0, 0, 0.05);
  margin-top: 10rpx;
  border-radius: 6rpx;
  font-size: 27rpx;
  color: #333;
  padding: 10rpx;
  max-width: 400rpx;
  word-break: break-all;
  display: flex;
  align-items: flex-start;

  .rname {
    flex-shrink: 0;
    margin-right: 10rpx;
  }

  .rcon {
    @include ellipsis(2);
  }

  .rimg {
    width: 100rpx;
  }
}

.l-chat-text-wapper {
  min-width: 100rpx;
  max-width: 515rpx;
  padding: 20rpx 20rpx;
  box-sizing: border-box;
  background-color: #ffffff;
  margin: 0 0 0 15rpx;
  position: relative;
  word-break: break-all;
  border-radius: 3px;
}

.l-chat-text-wapper::after {
  content: ' ';
  display: block;
  position: absolute;
  top: 40rpx;
  width: 0;
  height: 0;
  left: -10rpx;
  transform: translate(0, -50%);
  border: 15rpx solid;
  border-color: transparent #ffffff transparent transparent;
}

.l-chat-mine .l-chat-item-content {
  flex-direction: row-reverse;
}

.l-chat-mine .l-chat-avatar {
  margin: 0 0 0 20rpx;
}

.l-chat-mine .l-chat-name {
  text-align: right;
}

.l-chat-mine .l-chat-text {
  background-color: #95eb6c;
  color: #000;
  border-radius: 3px;
}

.l-chat-mine .l-chat-text::after {
  left: auto;
  right: -18rpx;
  border-color: transparent transparent transparent #95eb6c;
}

.l-chat-mine {
  .l-chat-view {
    align-items: flex-end;
  }

  .message-red-packet::after {
    left: auto;
    right: -18rpx;
    border-color: transparent transparent transparent orange;
  }
}

.l-chat-location {
  background-color: #fff;
  border: 8rpx;
  overflow: hidden;
  max-width: 350rpx;
  border-radius: 20rpx;

  .l-chat-con {
    padding: 20rpx;
    font-size: 26rpx;
  }
}

.l-chat-file {
  line-height: 1;
  margin: 0;
  text-align: left;
  padding: 20rpx;
  width: 420rpx;
  background-color: #ededed;
}

.l-chat-flie-view {
  display: flex;
}

.l-upload-img {
  border-radius: 6rpx;
}

.message-red-packet {
  position: relative;
  border-radius: 8rpx;
  background: orange;
  color: #fff;
  text-align: left;
  display: inline-table;
  max-width: 300px;
  min-width: 200px;
  height: 70px;
  box-shadow: 1px 1px 1px 1px #efefef;

  &::after {
    content: ' ';
    display: block;
    position: absolute;
    top: 34rpx;
    width: 0;
    height: 0;
    left: -18rpx;
    transform: translate(0, -50%);
    border: 10rpx solid;
    border-color: transparent orange transparent transparent;
  }

  &.chai {
    opacity: 0.4;
  }

  .contents {
    padding: 20rpx;
    display: inline-flex;
    max-width: 100%;
    align-items: center;
    position: relative;
    min-height: 80rpx;
    line-height: 40rpx;
    text-align: left;
    height: 60px;
    color: #fff;
  }

  .packet {
    padding-left: 15rpx;
    display: flex;
    flex-direction: column;
    color: rgba(255, 255, 255, 0.93);

    .name {
      font-size: 28rpx;
      font-weight: bold;
      font-family: 'Franklin Gothic Medium', 'Arial Narrow', Arial, sans-serif;
      max-width: 250rpx;
      @include ellipsis();
    }

    .content {
      font-size: 24rpx;
      @include ellipsis();
    }
  }

  .footer {
    font-size: 20rpx;
    height: 20px;
    padding: 4rpx 12rpx 0 12px;
    color: rgba(255, 255, 255, 0.5);
    display: flex;
    justify-content: space-between;
  }
}

.msg-product {
  background: #fff;
  padding: 20rpx;
  border-radius: 8rpx;

  .imgCover {
    position: relative;
    width: 300rpx;
    flex-shrink: 0;
    margin-right: 20rpx;

    .img {
      width: 100%;
      border-radius: $section-raduis;
    }
  }

  .content {
    text-align: left;

    .name {
      @include ellipsis;
      font-size: 28rpx;
      margin-bottom: 18rpx;
    }

    .money {
      color: red;
      font-size: 26rpx;
      margin-top: 10rpx;
    }
  }
}
</style>
